<template>
  <el-container class="data-source-container">
    <el-aside width="300px" class="data-source-aside">
      <el-container>
        <el-header height="40px">
          <el-button type="text" size="small" icon="el-icon-plus" @click="handleAdd">{{$t('fm.datasource.config.add')}}</el-button>
        </el-header>
        <el-main>
          <el-menu class="data-source-aside-menu" :default-active="selectKey" @select="handleSelect">
            <el-menu-item :index="item.key" v-for="(item, index) in list" :key="item.key" :disabled="!saved" @click.native="handleSelect(item.key)">
              <div slot="title">
                <span class="data-source-menu-i" :class="item.method">{{item.method}}</span>
                <div class="data-source-menu-label">{{item.name}}</div>
                <div class="data-source-menu-action">
                  <i class="iconfont icon-icon_clone" @click.stop="handleClone(index)" :title="$t('fm.tooltip.clone')"></i>
                  <i class="iconfont icon-trash" @click.stop="handleRemove(index)" :title="$t('fm.tooltip.trash')"></i>
                </div>
              </div>
            </el-menu-item>

          </el-menu>
        </el-main>
      </el-container>
    </el-aside>
    <el-main class="data-source-main">
      <el-container v-if="selectIndex >= 0">
        <el-header height="40px">
          <div class="data-source-action">
            <el-button type="primary" size="mini" @click="handleSave">{{$t('fm.datasource.config.save')}}</el-button>
            <el-button  size="mini" @click="handleTest">{{$t('fm.datasource.config.test')}}</el-button>
            <el-button size="mini" @click="handleCancal">{{$t('fm.datasource.config.cancel')}}</el-button>
          </div>
        </el-header>
        <el-main>
          <el-form ref="dataForm" :model="formData" :rules="formRules" :label-width="$lang == 'zh-CN' ? '79px' : '119px'" size="small" label-position="right" :key="selectKey">
            <el-form-item :label="$t('fm.datasource.edit.name')" prop="name">
              <el-input v-model="formData.name"></el-input>
            </el-form-item>
            <el-form-item :label="$t('fm.datasource.edit.url')" prop="url">
              <el-input disabled type="textarea" :rows="1" v-model="formData.url" autosize></el-input>
            </el-form-item>
            <el-form-item :label="$t('fm.datasource.edit.method')" prop="method">
              <el-radio-group v-model="formData.method">
                <el-radio-button label="GET" ></el-radio-button>
                <el-radio-button label="POST"></el-radio-button>
                <el-radio-button label="PUT"></el-radio-button>
                <el-radio-button label="DELETE"></el-radio-button>
              </el-radio-group>
            </el-form-item>
            <el-form-item :label="$t('fm.datasource.edit.headers')">
              <array-dynamic v-model="formData.headers"></array-dynamic>
            </el-form-item>
            <el-form-item :label="$t('fm.datasource.edit.params')">
              <array-dynamic v-model="formData.params"></array-dynamic>
            </el-form-item>
            <el-form-item :label="$t('fm.datasource.edit.auto')" :label-width="$lang == 'zh-CN' ? '175px' : '335px'">
              <el-switch
                v-model="formData.auto">
              </el-switch>
            </el-form-item>

            <el-form-item :label="$t('fm.datasource.edit.response')">
              <el-collapse :value="['1', '2', '3']">
                <el-collapse-item name="1" :title="$t('fm.datasource.edit.willRequest')">
                  <div class="code-desc" v-if="$lang == 'zh-CN'">// config: 发出请求的可用配置选项;</div>
                  <div class="code-desc" v-if="$lang == 'zh-CN'">// 通过 config.url 可以更改请求地址，通过 config.headers 可以更改请求头部</div>
                  <div class="code-desc" v-if="$lang == 'zh-CN'">// 通过 config.data 可以更改发送的数据，（GET 请求不适用，需要更改 config.params）</div>
                  <div class="code-line">(config) => {</div>
                  <code-editor v-model="formData.requestFunc" mode="javascript" height="120px"></code-editor>
                  <div class="code-line">}</div>
                </el-collapse-item>
                <el-collapse-item :title="$t('fm.datasource.edit.responseSuccess')" name="2">
                  <div class="code-desc" v-if="$lang == 'zh-CN'">// {{$t('fm.datasource.edit.annotation')}}</div>
                  <div class="code-line">(res) => {</div>

                  <code-editor v-model="formData.responseFunc" mode="javascript" height="120px"></code-editor>
                  <div class="code-line">}</div>
                </el-collapse-item>
                <el-collapse-item :title="$t('fm.datasource.edit.requestError')" name="3">
                  <div class="code-line">(error) => {</div>

                  <code-editor v-model="formData.errorFunc" mode="javascript" height="120px"></code-editor>
                  <div class="code-line">}</div>
                </el-collapse-item>
              </el-collapse>
            </el-form-item>
          </el-form>
        </el-main>
      </el-container>
    </el-main>
  </el-container>
</template>

<script>
import ArrayDynamic from './arrayDynamic'
import CodeEditor from '../CodeEditor'

export default {
  components: {
    ArrayDynamic,
    CodeEditor
  },
  props: {
    value: {
      type: Array,
      default: () => []
    }
  },
  data () {
    return {
      formData: {
        key: '',
        name: '',
        url: '',
        method: 'GET',
        auto: true,
        params: [],
        headers: [],
        responseFunc: `return res;`,
        requestFunc: `return config;`,
        errorFunc: ``
      },
      formRules: {
        name: [
          {required: true, message: ' '},
          { validator: (rule, value, callback) => {
            let currentItem = this.historyList.find(item => item.name == value)

            if (currentItem && currentItem.key != this.selectKey) {
              callback(new Error(this.$t('fm.datasource.message.repeat')))
            } else {
              callback()
            }
          }}
        ],
        url: [
          {required: true, message: ' '}
        ]
      },
      list: [...this.value],
      selectIndex: -1,
      selectKey: '',
      historyList: [...this.value],
      saved: true
    }
  },
  methods: {
    handleTest () {
      this.$refs.dataForm.validate((valid) => {
        if (valid) {
          let options = {
            method: this.formData.method,
            url: this.formData.url,
            headers: (() => {
              let headObj = {}
              this.formData.headers.forEach(item => {
                if (item.key) {
                  headObj[item.key] = item.value
                }
              })
              return headObj
            })()
          }

          options.params = (() => {
            let paramsObj = {}
            this.formData.params.forEach(item => {
              if (item.key) {
                paramsObj[item.key] = item.value
              }
            })
            return paramsObj
          })()

          this.$send(options).then(res => {
            let data = Function('res', this.formData.responseFunc)(res.data)

            console.log('==', data)
            this.$alert(data)
          }).catch(err => {
            this.$alert(err.message)
          })
        } else {
          this.$message.warning(this.$t('fm.datasource.message.settingError'))
        }
      })
    },

    handleSave () {
      this.$refs.dataForm.validate((valid) => {
        if (valid) {
          let options = {
            ...this.formData,
            params: (() => {
              let paramsObj = {}
              this.formData.params.forEach(item => {
                if (item.key) {
                  paramsObj[item.key] = item.value
                }
              })
              return paramsObj
            })(),
            headers: (() => {
              let headersObj = {}
              this.formData.headers.forEach(item => {
                if (item.key) {
                  headersObj[item.key] = item.value
                }
              })
              return headersObj
            })()
          }

          this.$set(this.list, this.list.findIndex(item => item.key === this.selectKey), options)

          this.historyList = [...this.list]

          this.saved = true

          this.$emit('input', this.historyList)

          this.$message.success(this.$t('fm.datasource.message.saveSuccess'))
        } else {
          this.$message.warning(this.$t('fm.datasource.message.settingError'))
        }
      })
    },

    handleAdd () {
      if (!this.saved) {
        this.$message.warning(this.$t('fm.datasource.message.saveError'))
        return
      }

      let key = Math.random().toString(36).slice(-8)

      this.list.push({
        key: key,
        name: 'DataSource_' + key,
        url: '',
        method: 'GET',
        auto: true,
        params: {},
        headers: {},
        responseFunc: 'return res;',
        requestFunc: `return config;`
      })
      this.selectKey = key

      this.saved = false
    },

    loadForm () {
      let currentData = this.list[this.selectIndex]

      this.formData = {
        ...currentData,
        params: currentData.params && Object.keys(currentData.params).map(item => ({key: item, value: currentData.params[item]})) || [],
        headers: currentData.headers && Object.keys(currentData.headers).map(item => ({key: item, value: currentData.headers[item]})) || [],
        requestFunc: currentData.requestFunc || `return config;`
      }
    },

    handleSelect (key) {
      if (key === this.selectKey) {
        return
      }
      if (!this.saved) {
        this.$message.warning(this.$t('fm.datasource.message.saveError'))
        return
      }

      this.selectKey = key
    },

    handleCancal () {
      this.selectKey = ''

      this.list = [...this.historyList]

      this.saved = true
    },

    handleClone (index) {
      if (!this.saved) {
        this.$message.warning(this.$t('fm.datasource.message.saveError'))
        return
      }
      let currentData = this.list[index]

      let key = Math.random().toString(36).slice(-8)

      let cloneData = {
        ...currentData,
        key,
        name: currentData.name + '_copy'
      }

      this.list.push(cloneData)

      this.selectKey = key

      this.saved = false
    },

    handleRemove (index) {
      let currentData = this.list[index]

      if (currentData.key === this.selectKey) {
        this.selectKey = ''
        this.saved = true
      }
      this.list.splice(index, 1)
      if (index < this.historyList.length) {
        this.historyList.splice(index, 1)
      }

      this.$emit('input', this.historyList)
    }
  },
  watch: {
    selectKey (val) {
      if (val) {
        this.selectIndex = this.list.findIndex(item => item.key === val)

        this.loadForm()
      } else {
        this.selectIndex = -1
      }
    },
    value (val) {
      this.historyList = [...val]
      this.list = [...val]
    }
  }
}
</script>

<style lang="scss">
.data-source-container{
  .data-source-main{
    padding: 0;

    >.el-container{
      display: flex;
      height: 100%;

      >.el-header{
        padding: 5px;
        border-bottom: 1px solid #eee;
        background: #F2F6FC;
      }
    }

    .data-source-action{
      text-align: right;
    }

    .code-line{
      font-size: 14px;
      color: blue;
      font-weight: 500;
    }

    .code-desc{
      margin-left: 2px;
      font-size: 12px;
      color: #999;
    }

    .el-collapse-item{
      border: 1px solid #EBEEF5;
    }

    .el-collapse-item__header{
      background: #EBEEF5;
      // border: 0;
      height: 36px;
      line-height: 36px;
      padding: 5px;
    }

    .el-collapse-item__wrap{
      border: 0;

      .el-collapse-item__content{
        padding: 5px;
      }
    }
  }

  .data-source-aside{
    border-right: 1px solid #eee;

    >.el-container{
      display: flex;
      height: 100%;

      >.el-main{
        margin: 0;
        padding: 0;
      }

      >.el-header{
        padding: 5px;
        border-bottom: 1px solid #eee;
        background: #F2F6FC;
      }
    }

    .data-source-aside-menu{
      margin: 10px;
      border-right: 0;

      .el-menu-item{
        border: 1px solid #DCDFE6;
        background: #fff;
        border-radius: 3px;
        padding: 10px !important;
        height: auto;
        line-height: 1;
        cursor: default;
        position: relative;

        &.is-disabled{
          opacity: 1;
          cursor: default;
          background: #fff;
        }

        &.is-active{
          background: #E4E7ED;
          color: #303133;
        }

        &.is-active.is-disabled{
          background: #E4E7ED !important;
          color: #303133;
        }

        +.el-menu-item{
          margin-top: 6px;
        }
      }

      .data-source-menu-label{
        overflow:hidden;
        text-overflow:ellipsis;
        white-space:nowrap;
        display: inline-block;
        width: 180px;
        margin-left: 40px;
      }

      .data-source-menu-i{
        position: absolute;
        font-size: 12px;
        left: 2px;
        top: 13px;
        width: 45px;
        text-align: center;

        &.GET{
          color: #67C23A;
        }

        &.POST{
          color: #E6A23C;
        }

        &.PUT{
          color: #409EFF;
        }

        &.DELETE{
          color: #F56C6C;
        }
      }

      .data-source-menu-action{
        display: inline-block;
        padding-right: 10px;
        color: #666;
        font-weight: 600;

        >i{
          cursor: pointer;
          margin-left: 5px;
        }
      }
    }
  }
}
</style>
